package net.zoneland.greenleaf.timer.task;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.zoneland.greenleaf.GLOBAL;
import net.zoneland.greenleaf.timer.entity.Sys_schedulejob;
import net.zoneland.greenleaf.timer.service.Sys_schedulejobServiceI;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.web.context.WebApplicationContext;


public class TaskUtils_LOCALHOST {
	
	public final static Logger log = Logger.getLogger(TaskUtils_LOCALHOST.class);
	private WebApplicationContext springContext = GLOBAL.springContext;
	/**
	 * 加载所有的定时任务
	 * 从数据库中获取所有的定时任务，并且启动定时任务
	 */
	public void runAllTask(){
		String localHost =null ;
		try {
			localHost = InetAddress.getLocalHost().getHostAddress().toString();
		} catch (UnknownHostException e) {
			log.error("系统异常", e);
		}  
		Sys_schedulejobServiceI sys_schedulejobService = (Sys_schedulejobServiceI)springContext.getBean("sys_schedulejobService");		 
		
		//这里获取任务信息数据
		Map<String, Object> paramMap =  new HashMap<String, Object>();
		paramMap.put("jobstatus", "1" );
		paramMap.put("isautostart", 1 );
		List<Sys_schedulejob> jobList = sys_schedulejobService.getList(paramMap);
		if( jobList != null ){
			log.info( localHost+"一共有["+jobList.size()+"]个定时任务需要加载，尝试加载定时任务......" );
			for (Sys_schedulejob job : jobList) {
				
				String description = job.getDescription();
				if(description==null||description.equals("")||description.equals("*")||( localHost!=null&&( localHost.indexOf(description)!=-1||description.indexOf(localHost)!=-1))){
					log.debug("尝试加载定时任务:" + job.getJobname());
					addJob( job );
					log.debug("定时任务["+job.getJobname()+"]加载完成。");
				}else{
					log.debug(localHost+"无法执行定时任务:" + job.getJobname());
				}
				
			}
			log.info("所有的定时任务已加载完成。");
		}
	}
	
	/**
	 * 停止所有的定时任务
	 * 从数据库中获取所有的定时任务，并且停止定时任务
	 */
	public void stopAllTask(){
		Sys_schedulejobServiceI sys_schedulejobService = (Sys_schedulejobServiceI)springContext.getBean("sys_schedulejobService");		 
		//这里获取任务信息数据
		Map<String, Object> paramMap =  new HashMap<String, Object>();
		List<Sys_schedulejob> jobList = sys_schedulejobService.getList(paramMap);
		if( jobList != null ){
			log.info("一共有["+jobList.size()+"]个定时任务需要加载，尝试停止定时任务......");
			for (Sys_schedulejob job : jobList) {
				log.debug("尝试停止定时任务:" + job.getJobname());
				try {
					deleteJob( job );
				} catch (SchedulerException e) {
					log.error("系统异常", e);
				}
				log.debug("定时任务["+job.getJobname()+"]停止完成。");
			}
			log.info("所有的定时任务已停止完成。");
		}
	}
	
	/**
	 * 启动执行一个定时任务
	 * @param schedulerFactoryBean
	 * @param job
	 */
	public void addJob( Sys_schedulejob job ){
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		CronTrigger trigger = null;
		CronScheduleBuilder scheduleBuilder = null;
		TriggerKey triggerKey = null;
		//获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
		try {
			triggerKey = TriggerKey.triggerKey(job.getJobname(), job.getJobgroup());
			trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		} catch (SchedulerException e1) {
			log.error("系统异常", e1);
		}		 
		//不存在，创建一个
		if (null == trigger) {
			JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withIdentity(job.getJobname(), job.getJobgroup()).build();
			jobDetail.getJobDataMap().put("scheduleJob", job);
			//表达式调度构建器
			scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronexpression());
			//按新的cronExpression表达式构建一个新的trigger
			trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobname(), job.getJobgroup()).withSchedule(scheduleBuilder).build();
			try {
				scheduler.scheduleJob(jobDetail, trigger);
			} catch (SchedulerException e) {
				log.error("系统异常", e);
			}
		} else {
			// Trigger已存在，那么更新相应的定时设置
			//表达式调度构建器
			scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronexpression());
			//按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			//按新的trigger重新设置job执行
			try {
				scheduler.rescheduleJob(triggerKey, trigger);
			} catch (SchedulerException e) {
				log.error("系统异常", e);
			}
		}
	}

	/**
	 * 通过反射调用scheduleJob中定义的方法
	 * 
	 * @param scheduleJob
	 */
	public static void invokMethod( Sys_schedulejob scheduleJob ) {		
		Object object = null;
		Class clazz = null;
                //springId不为空先按springId查找bean
		if (StringUtils.isNotBlank(scheduleJob.getSpringid())) {
			object = GLOBAL.springContext.getBean(scheduleJob.getSpringid());
		} else if (StringUtils.isNotBlank(scheduleJob.getBeanclass())) {
			try {
				clazz = Class.forName(scheduleJob.getBeanclass());
				object = clazz.newInstance();
			} catch (Exception e) {
				log.error("系统异常", e);
			}
		}
		if (object == null) {
			log.error("任务名称 = [" + scheduleJob.getJobname() + "]---------------未启动成功，请检查是否配置正确！！！");
			return;
		}
		clazz = object.getClass();
		Method method = null;
		try {
			method = clazz.getDeclaredMethod(scheduleJob.getMethodname());
		} catch (NoSuchMethodException e) {
			log.error("任务名称 = [" + scheduleJob.getJobname() + "]---------------未启动成功，方法名设置错误！！！");
		} catch (SecurityException e) {
			log.error("系统异常", e);
		}
		if (method != null) {
			try {
				method.invoke(object);
			} catch (IllegalAccessException e) {
				log.error("系统异常", e);
			} catch (IllegalArgumentException e) {
				log.error("系统异常", e);
			} catch (InvocationTargetException e) {
				log.error("系统异常", e);
			}
		}
	}
	
	/**
	 * 获取所有计划中的任务列表
	 * 
	 * @return
	 * @throws SchedulerException
	 */
	public List<Sys_schedulejob> getAllJob() throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		List<Sys_schedulejob> jobList = new ArrayList<Sys_schedulejob>();
		for (JobKey jobKey : jobKeys) {
			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
			for (Trigger trigger : triggers) {
				Sys_schedulejob job = new Sys_schedulejob();
				job.setJobname(jobKey.getName());
				job.setJobgroup(jobKey.getGroup());
				job.setDescription("触发器:" + trigger.getKey());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
				job.setJobstatus(triggerState.name());
				if (trigger instanceof CronTrigger) {
					CronTrigger cronTrigger = (CronTrigger) trigger;
					String cronExpression = cronTrigger.getCronExpression();
					job.setCronexpression(cronExpression);
				}
				jobList.add(job);
			}
		}
		return jobList;
	}
	
	/**
	 * 所有正在运行的job
	 * 
	 * @return
	 * @throws SchedulerException
	 */
	public List<Sys_schedulejob> getRunningJob() throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
		List<Sys_schedulejob> jobList = new ArrayList<Sys_schedulejob>(executingJobs.size());
		for (JobExecutionContext executingJob : executingJobs) {
			Sys_schedulejob job = new Sys_schedulejob();
			JobDetail jobDetail = executingJob.getJobDetail();
			JobKey jobKey = jobDetail.getKey();
			Trigger trigger = executingJob.getTrigger();
			job.setJobname(jobKey.getName());
			job.setJobgroup(jobKey.getGroup());
			job.setDescription("触发器:" + trigger.getKey());
			Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
			job.setJobstatus(triggerState.name());
			if (trigger instanceof CronTrigger) {
				CronTrigger cronTrigger = (CronTrigger) trigger;
				String cronExpression = cronTrigger.getCronExpression();
				job.setCronexpression(cronExpression);
			}
			jobList.add(job);
		}
		return jobList;
	}
	
	/**
	 * 暂停一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void pauseJob(Sys_schedulejob scheduleJob) throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobname(), scheduleJob.getJobgroup());
		scheduler.pauseJob(jobKey);
	}

	/**
	 * 恢复一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void resumeJob(Sys_schedulejob scheduleJob) throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobname(), scheduleJob.getJobgroup());
		scheduler.resumeJob(jobKey);
	}

	/**
	 * 删除一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void deleteJob(Sys_schedulejob scheduleJob) throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobname(), scheduleJob.getJobgroup());
		scheduler.deleteJob(jobKey);
	}

	/**
	 * 立即执行job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void runAJobNow(Sys_schedulejob scheduleJob) throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		JobKey jobKey = JobKey.jobKey(scheduleJob.getJobname(), scheduleJob.getJobgroup());
		scheduler.triggerJob(jobKey);
	}

	/**
	 * 更新job时间表达式
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void updateJobCron(Sys_schedulejob scheduleJob) throws SchedulerException {
		//从spring上下文中获取schedulerFactoryBean对象
		Scheduler scheduler = (Scheduler)springContext.getBean("schedulerFactoryBean");
		TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobname(), scheduleJob.getJobgroup());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronexpression());
		if( trigger!=null){
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			scheduler.rescheduleJob(triggerKey, trigger);
		}
	}
}